package main

import (
	"embed"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/spf13/cobra"
)

// 嵌入所有外部工具（假设这些文件与main.go同目录）
//
//go:embed tools/MegaCli64 tools/arcconf tools/storcli64 tools/ssacli
var toolsFS embed.FS

// 临时目录，用于存放提取的工具
var tmpDir string

// 通用工具：提取嵌入的工具到临时目录并返回路径
func extractTool(embeddedPath string) (string, error) {
	// 读取嵌入的文件内容
	content, err := toolsFS.ReadFile(embeddedPath)
	if err != nil {
		return "", err
	}

	// 确定临时文件路径（保持原文件名）
	filename := filepath.Base(embeddedPath)
	tmpPath := filepath.Join(tmpDir, filename)

	// 写入临时文件并赋予执行权限
	file, err := os.Create(tmpPath)
	if err != nil {
		return "", err
	}
	defer file.Close()

	if _, err := io.WriteString(file, string(content)); err != nil {
		return "", err
	}
	if err := os.Chmod(tmpPath, 0755); err != nil {
		return "", err
	}

	return tmpPath, nil
}
func main() {
	// 初始化临时目录（程序退出时清理）
	var err error
	tmpDir, err = os.MkdirTemp("", "raidtool-*")
	if err != nil {
		panic("创建临时目录失败: " + err.Error())
	}
	defer os.RemoveAll(tmpDir)

	// 根命令
	var rootCmd = &cobra.Command{
		Use:   "raidtool",
		Short: "整合RAID管理工具的统一入口",
		Long:  "通过统一命令调用StorCLI、MegaCli和arcconf",
	}

	// 添加子命令（每个工具对应一个子命令）

	rootCmd.AddCommand(newGetPdListCmd())
	rootCmd.AddCommand(newGetLdListCmd())

	// 执行命令
	if err := rootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}

// 创建获取物理磁盘列表的命令
func newGetPdListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "getPdList",
		Short: "获取物理磁盘列表",
		Long:  "自动检测RAID控制器并获取所有物理磁盘的信息",
		RunE:  runGetPdListAuto,
	}
	return cmd
}
func newGetLdListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "getLdList",
		Short: "获取逻辑磁盘列表",
		Long:  "自动检测RAID控制器并获取所有逻辑磁盘的信息",
		RunE:  runGetLdListAuto,
	}
	return cmd
}

// 自动检测控制器类型并执行相应的命令
// 硬盘类
func runGetPdListAuto(cmd *cobra.Command, args []string) error {
	controllerType, err := detectControllerType()
	if err != nil {
		return err
	}

	switch controllerType {
	case "megacli":
		fmt.Println("使用MegaCli工具获取物理磁盘列表")
		return runMegacliGetPdList(cmd, args)
	case "arcconf":
		fmt.Println("使用Arcconf工具获取物理磁盘列表")
		return runArcconfGetPdList(cmd, args)
	case "storcli":
		fmt.Println("使用StorCLI工具获取物理磁盘列表")
		return runstorcliGetPdList(cmd, args)
	case "ssacli":
		fmt.Println("使用SSACLI工具获取物理磁盘列表")
		return runssacliGetPdList(cmd, args)

	default:
		fmt.Println("默认使用MegaCli工具获取物理磁盘列表")
		return runMegacliGetPdList(cmd, args) // 默认使用megacli
	}
}

// runGetLdListAuto 自动检测控制器类型并执行相应的命令
// 逻辑盘类
func runGetLdListAuto(cmd *cobra.Command, args []string) error {
	controllerType, err := detectControllerType()
	if err != nil {
		return err
	}

	switch controllerType {
	case "megacli":
		fmt.Println("使用MegaCli工具获取逻辑磁盘列表")
		return runMegacliGetLdList(cmd, args)
	case "arcconf":
		fmt.Println("使用Arcconf工具获取逻辑磁盘列表")
		return runArcconfGetLdList(cmd, args)
	case "storcli":
		fmt.Println("使用StorCLI工具获取逻辑磁盘列表")
		return runstorcliGetLdList(cmd, args)
	case "ssacli":
		fmt.Println("使用SSACLI工具获取物理磁盘列表")
		return runssacliGetLdList(cmd, args)

	default:
		fmt.Println("默认使用MegaCli工具获取逻辑磁盘列表")
		return runMegacliGetLdList(cmd, args) // 默认使用megacli
	}
}

// detectControllerType 检测RAID控制器类型
func detectControllerType() (string, error) {

	// 尝试检测Adaptec控制器
	arcconfPath, err := extractTool("tools/arcconf")
	if err == nil {
		cmd := exec.Command(arcconfPath, "LIST")
		output, _ := cmd.CombinedOutput()
		//fmt.Println(string(output))
		//fmt.Println("检测Adaptec控制器.....")

		if strings.Contains(string(output), "Controllers found:") &&
			!strings.Contains(string(output), "Controllers found: 0") {
			// 存在控制器
			fmt.Println("检测到Adaptec控制器")

			return "arcconf", nil
		}
	} else {
		fmt.Println("Error: ", err)
	}
	storcliPath, err := extractTool("tools/storcli64")
	if err == nil {
		cmd := exec.Command(storcliPath, "show")
		output, _ := cmd.CombinedOutput()
		//fmt.Println(string(output))
		//fmt.Println("检测LSI MegaRAID控制器.....")

		if strings.Contains(string(output), "Number of Controllers") &&
			!strings.Contains(string(output), "Number of Controllers = 0") {
			// 存在控制器
			fmt.Println("检测到LSI MegaRAID控制器")

			return "storcli", nil
		}
	} else {
		fmt.Println("Error: ", err)
	}
	// 尝试检测MegaRAID控制器
	megacliPath, err := extractTool("tools/MegaCli64")
	if err == nil {
		cmd := exec.Command(megacliPath, "-adpCount", "-NoLog")
		output, _ := cmd.CombinedOutput()

		if strings.Contains(string(output), "Controller Count: ") &&
			!strings.Contains(string(output), "Controller Count: 0") {
			// 存在控制器
			fmt.Println("检测到MegaRAID控制器")
			return "megacli", nil
		}
	} else {
		fmt.Println("Error: ", err)
	}
	// 尝试检测MegaRAID控制器
	ssacliPath, err := extractTool("tools/ssacli")
	if err == nil {
		cmd := exec.Command(ssacliPath, "ctrl", "slot=0", "show", "status")
		output, _ := cmd.CombinedOutput()

		if strings.Contains(string(output), "Controller Status: OK") &&
			!strings.Contains(string(output), "No controllers detected") {
			// 存在控制器
			fmt.Println("检测到ssacli控制器")
			return "ssacli", nil
		}
	} else {
		fmt.Println("Error: ", err)
	}
	// 如果没有检测到控制器，默认使用megacli
	fmt.Println("未检测到特定控制器，使用默认设置")
	return "megacli", nil
}
